using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.Contracts;


namespace FoundationLib.AddIns.Constraints 
{
	/// <summary>
	/// Class for creating transformers for EA elements
	/// </summary>
	public class OclTransformerFactory 
	{
		/// <summary>
		/// Possible constraint types supported by this transformer
		/// </summary>
		private static readonly string[] classConstraintTypes = new string[] { "OCL" };
		/// <summary>
		/// Possible method constraint types supported by this transformer
		/// </summary>
		private static readonly string[] methodConstraintTypes = new string[] { "OCL" };


		/// <summary>
		/// Creates an OCL transformer for a class element in EA
		/// </summary>
		/// <returns>The OCL transformer instance</returns>
		/// <param name="classElement">The EA class element</param>
		public static OclTransformer Create(EA.Element classElement)
		{
			if (classElement == null)
				throw new ArgumentNullException("classElement");

			List<OclStatement> statements = new List<OclStatement>();
			foreach (EA.Constraint constraint in classElement.Constraints)
			{
				if (!classConstraintTypes.Contains(constraint.Type))
					continue;
				if (String.IsNullOrWhiteSpace(constraint.Notes))
					continue;
				statements.Add(new ClassOclStatement(constraint.Notes, constraint.Name));
			}

			return new OclTransformer(statements);
		}

		/// <summary>
		/// Creates a new OCL transformer using the given EA method element
		/// </summary>
		/// <returns>The OCL transformer instance</returns>
		/// <param name="methodElement">The method element in EA</param>
		/// <param name="constraintType">The type of constraint to generate</param>
		public static OclTransformer Create(EA.Method methodElement, MethodConstraintType constraintType)
		{
			if (methodElement == null)
				throw new ArgumentNullException("methodElement");

			List<OclStatement> statements = new List<OclStatement>();
			if (constraintType == MethodConstraintType.PreCondition)
			{
				foreach (EA.MethodConstraint constraint in methodElement.PreConditions)
				{
					if (!methodConstraintTypes.Contains(constraint.Type))
						continue;
					if (String.IsNullOrWhiteSpace(constraint.Notes))
						continue;
					statements.Add(new MethodOclStatement(constraint.Notes, constraint.Name, MethodConstraintType.PreCondition,
						methodElement.ReturnType, methodElement.ReturnIsArray));
				}
			}
			else if (constraintType == MethodConstraintType.PostCondition)
			{
				foreach (EA.MethodConstraint constraint in methodElement.PostConditions)
				{
					if (!methodConstraintTypes.Contains(constraint.Type))
						continue;
					if (String.IsNullOrWhiteSpace(constraint.Notes))
						continue;
					statements.Add(new MethodOclStatement(constraint.Notes, constraint.Name, MethodConstraintType.PostCondition,
						methodElement.ReturnType, methodElement.ReturnIsArray));
				}
			}
			return new OclTransformer(statements);
		}

	}

}